/*
 * Copyright (C) 2004-2007  Autodesk, Inc.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of version 2.1 of the GNU Lesser
 * General Public License as published by the Free Software Foundation.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "Pch.h"
#include "WcsTestSelect.h"

CPPUNIT_TEST_SUITE_REGISTRATION( WcsTestSelect );
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( WcsTestSelect, "WcsTestSelect");

WcsTestSelect::WcsTestSelect ()
{
}

WcsTestSelect::~WcsTestSelect ()
{
}

void WcsTestSelect::testGetBounds ()
{
    FdoPtr<FdoIConnection> conn = this->GetConnection ();
	try
	{
		conn->SetConnectionString (L"FeatureServer=http://nsidc.org/cgi-bin/atlas_north");
		CPPUNIT_ASSERT (FdoConnectionState_Open == conn->Open ());

		FdoPtr<FdoISelect> cmd = static_cast<FdoISelect *> (conn->CreateCommand (FdoCommandType_Select));
		cmd->SetFeatureClassName (L"sea_ice_concentration_02");	    
		FdoPtr<FdoIFeatureReader> featReader = cmd->Execute ();

		CPPUNIT_ASSERT (featReader->ReadNext ());
		FdoPtr<FdoIRaster> raster = featReader->GetRaster (L"Raster");
		FdoPtr<FdoByteArray> gba = raster->GetBounds ();
		FdoPtr<FdoFgfGeometryFactory> factory = FdoFgfGeometryFactory::GetInstance ();
		FdoPtr<FdoIGeometry> geom = factory->CreateGeometryFromFgf (gba.p);
		FdoPtr<FdoIEnvelope> enve = geom->GetEnvelope ();

		CPPUNIT_ASSERT (enve->GetMinX() == -3961770.085);
		CPPUNIT_ASSERT (enve->GetMinY() == -3961769.906);
		CPPUNIT_ASSERT (enve->GetMaxX() == 3961769.894);
		CPPUNIT_ASSERT (enve->GetMaxY() == 4362961.971);
#ifdef _DEBUG
		wprintf (L"Extent: (%f,%f %f,%f)\n", enve->GetMinX(), enve->GetMinY(), enve->GetMaxX(), enve->GetMaxY());                
#endif
	}
	catch (FdoException* e) 
    {
        fail (e);
	}
}

// http://nsidc.org/cgi-bin/atlas_north
void WcsTestSelect::testServer1 ()
{
    try
    {
	    FdoPtr<FdoIConnection> conn = this->GetConnection ();
	    conn->SetConnectionString (L"FeatureServer=http://nsidc.org/cgi-bin/atlas_north");        
        CPPUNIT_ASSERT (FdoConnectionState_Open == conn->Open ());

	    FdoPtr<FdoISelect> cmd = static_cast<FdoISelect *> (conn->CreateCommand (FdoCommandType_Select));
	    cmd->SetFeatureClassName (L"greenland_accumulation");
	    FdoPtr<FdoIFeatureReader> featReader = cmd->Execute ();
        
	    // Layer "greenland_accumulation"
	    CPPUNIT_ASSERT (featReader->ReadNext ());
	    FdoPtr<FdoIRaster> raster = featReader->GetRaster (L"Raster");
	    CPPUNIT_ASSERT (!featReader->ReadNext ());

	    // Layer "snow_water_equivalent_08"
	    cmd->SetFeatureClassName (L"snow_water_equivalent_08");
	    featReader = cmd->Execute ();
	    CPPUNIT_ASSERT (featReader->ReadNext ());
	    raster = featReader->GetRaster (L"Raster");
	    CPPUNIT_ASSERT (!featReader->ReadNext ());

        // Layer "snow_water_equivalent_01"
	    cmd->SetFeatureClassName (L"snow_water_equivalent_01");
	    featReader = cmd->Execute ();
	    CPPUNIT_ASSERT (featReader->ReadNext ());
	    raster = featReader->GetRaster (L"Raster");
	    CPPUNIT_ASSERT (!featReader->ReadNext ());

        conn->Close ();
    }
    catch (FdoException* e)
    {
        fail(e);
    }
}

void WcsTestSelect::testServer2 ()
{
    try
    {        
	    FdoPtr<FdoIConnection> conn = this->GetConnection ();
	    conn->SetConnectionString (L"FeatureServer=http://sigma.openplans.org/geoserver/ows");        
        CPPUNIT_ASSERT (FdoConnectionState_Open == conn->Open ());

	    FdoPtr<FdoISelect> cmd = static_cast<FdoISelect *> (conn->CreateCommand (FdoCommandType_Select));
	    cmd->SetFeatureClassName (L"nurc Img_Sample");
	    FdoPtr<FdoIFeatureReader> featReader = cmd->Execute ();
        
	    // Layer "nurc:Img_Sample"
	    CPPUNIT_ASSERT (featReader->ReadNext ());
	    FdoPtr<FdoIRaster> raster = featReader->GetRaster (L"Raster");
	    CPPUNIT_ASSERT (!featReader->ReadNext ());
    }
    catch (FdoException* e)
    {
        fail(e);
    }
}

//http://nsidc.org/cgi-bin/atlas_north
void WcsTestSelect::testResample ()
{
    try
    {
	    FdoPtr<FdoIConnection> conn = this->GetConnection ();
	    conn->SetConnectionString (L"FeatureServer=http://nsidc.org/cgi-bin/atlas_north");
	    CPPUNIT_ASSERT (FdoConnectionState_Open == conn->Open ());

	    FdoICommand* cmd = conn->CreateCommand(FdoCommandType_Select);
	    FdoPtr<FdoISelect> cmdSelect = static_cast<FdoISelect*>(cmd);
	    cmdSelect->SetFeatureClassName(L"sea_ice_concentration_01");
    	

	    // set up clip function: CLIP(Image, 100, 100, 700.0, 500.0)
	    FdoPtr<FdoExpressionCollection> funcParams = FdoExpressionCollection::Create();
	    FdoPtr<FdoIdentifier> rasterProp = FdoIdentifier::Create(L"Image");
	    funcParams->Add(rasterProp);
	    FdoPtr<FdoDataValue> minX = FdoDataValue::Create(100, FdoDataType_Double);
	    funcParams->Add(minX);
	    FdoPtr<FdoDataValue> minY = FdoDataValue::Create(100, FdoDataType_Double);
	    funcParams->Add(minY);
	    FdoPtr<FdoDataValue> maxX = FdoDataValue::Create((FdoInt32(700)));
	    funcParams->Add(maxX);
	    FdoPtr<FdoDataValue> maxY = FdoDataValue::Create(500, FdoDataType_Double);
	    funcParams->Add(maxY);
	    FdoPtr<FdoDataValue> height = FdoDataValue::Create(800, FdoDataType_Double);
	    funcParams->Add(height);
	    FdoPtr<FdoDataValue> width = FdoDataValue::Create(600, FdoDataType_Double);
	    funcParams->Add(width);

	    FdoPtr<FdoFunction> resampleFunc = FdoFunction::Create(L"RESAMPLE", funcParams);
	    FdoPtr<FdoComputedIdentifier> resampleIdentifier = FdoComputedIdentifier::Create(L"resampledRaster", resampleFunc);
	    FdoPtr<FdoIdentifierCollection> propsToSelect = cmdSelect->GetPropertyNames();
    	
	    // add it to the properties to select
	    propsToSelect->Add(resampleIdentifier);

	    FdoPtr<FdoIFeatureReader> featureReader = cmdSelect->Execute();

	    while (featureReader->ReadNext ())
	    {
		    FdoPtr<FdoIRaster> raster = featureReader->GetRaster (L"resampledRaster");
		    FdoPtr<FdoIStreamReader> stream = raster->GetStreamReader ();		
	    }
    }
    catch (FdoException* e)
    {
        fail(e);
    }
}

void WcsTestSelect::testClip ()
{
    try
    {
	    FdoPtr<FdoIConnection> conn = this->GetConnection ();
	    conn->SetConnectionString (L"FeatureServer=http://nsidc.org/cgi-bin/atlas_north");
	    CPPUNIT_ASSERT (FdoConnectionState_Open == conn->Open ());

	    FdoICommand* cmd = conn->CreateCommand(FdoCommandType_Select);
	    FdoPtr<FdoISelect> cmdSelect = static_cast<FdoISelect*>(cmd);
	    cmdSelect->SetFeatureClassName(L"sea_ice_concentration_01");
        
	    // set up clip function: CLIP(Image, 0, 0, 1000000,1000000)
	    FdoPtr<FdoExpressionCollection> funcParams = FdoExpressionCollection::Create();
	    FdoPtr<FdoIdentifier> rasterProp = FdoIdentifier::Create(L"Image");
	    funcParams->Add(rasterProp);
	    FdoPtr<FdoDataValue> minX = FdoDataValue::Create(0.0, FdoDataType_Double);
	    funcParams->Add(minX);
	    FdoPtr<FdoDataValue> minY = FdoDataValue::Create(0.0, FdoDataType_Double);
	    funcParams->Add(minY);
	    FdoPtr<FdoDataValue> maxX = FdoDataValue::Create((FdoInt32(100000)));
	    funcParams->Add(maxX);
	    FdoPtr<FdoDataValue> maxY = FdoDataValue::Create(100000, FdoDataType_Double);
	    funcParams->Add(maxY);

	    FdoPtr<FdoFunction> clipFunc = FdoFunction::Create(L"CLIP", funcParams);
	    FdoPtr<FdoComputedIdentifier> clipIdentifier = FdoComputedIdentifier::Create(L"clippedRaster", clipFunc);
	    FdoPtr<FdoIdentifierCollection> propsToSelect = cmdSelect->GetPropertyNames();
    	
	    // add it to the properties to select
	    propsToSelect->Add(clipIdentifier);

	    FdoPtr<FdoIFeatureReader> featureReader = cmdSelect->Execute();

	    while (featureReader->ReadNext ())
	    {
		    FdoPtr<FdoIRaster> raster = featureReader->GetRaster (L"clippedRaster");
		    FdoPtr<FdoIStreamReader> stream = raster->GetStreamReader ();		
	    }
    }
    catch (FdoException* e)
    {
        fail(e);
    }
}

// http://nsidc.org/cgi-bin/atlas_north
void WcsTestSelect::testNsidc()
{
    try
    {
        ExecuteSelectServer(L"http://nsidc.org/cgi-bin/atlas_north", L"sea_ice_concentration_04");
    }
    catch (FdoException* e)
    {
        fail(e);
    }
}


void WcsTestSelect::ExecuteSelectServer(FdoString* server, FdoString* classname)
{
    FdoPtr<FdoIConnection> connection = WcsTests::GetConnection ();

    FdoStringP sServer = FdoStringP::Format(L"FeatureServer=%ls", server);
    connection->SetConnectionString((FdoString*)sServer);
    FdoConnectionState state = connection->Open ();

    FdoPtr<FdoIDescribeSchema> cmdDS = static_cast<FdoIDescribeSchema *> (connection->CreateCommand (FdoCommandType_DescribeSchema));
    FdoPtr<FdoFeatureSchemaCollection> schemas = cmdDS->Execute ();
    FdoInt32 cntSchemas = schemas->GetCount ();
    CPPUNIT_ASSERT (cntSchemas > 0);
    FdoPtr<FdoFeatureSchema> schema = schemas->GetItem (0);
    FdoPtr<FdoClassCollection> classes = schema->GetClasses ();
    FdoInt32 cntClasses = classes->GetCount ();
    CPPUNIT_ASSERT (cntClasses > 0);

    FdoPtr<FdoISelect> cmdSelect = static_cast<FdoISelect*> (connection->CreateCommand (FdoCommandType_Select));
    cmdSelect->SetFeatureClassName (classname);
    FdoPtr<FdoIFeatureReader> featReader = cmdSelect->Execute ();
    CPPUNIT_ASSERT (featReader->ReadNext ());	    
    FdoPtr<FdoIRaster> raster = featReader->GetRaster (L"Raster");

    FdoPtr<FdoByteArray> gba = raster->GetBounds ();
    FdoPtr<FdoFgfGeometryFactory> factory = FdoFgfGeometryFactory::GetInstance ();
    FdoPtr<FdoIGeometry> geom = factory->CreateGeometryFromFgf (gba.p);
    FdoPtr<FdoIEnvelope> enve = geom->GetEnvelope ();

#ifdef _DEBUG
    wprintf (L"Extent: (%f,%f %f,%f)\n", enve->GetMinX(), enve->GetMinY(), enve->GetMaxX(), enve->GetMaxY());                
#endif

    FdoPtr<FdoIStreamReader> stream = raster->GetStreamReader ();
    FdoIStreamReader* streamReader = raster->GetStreamReader ();
    FdoPtr<FdoIStreamReaderTmpl<FdoByte> > byteStreamReader = static_cast<FdoIStreamReaderTmpl<FdoByte>*> (streamReader);

    CPPUNIT_ASSERT (streamReader != NULL);
    CPPUNIT_ASSERT (byteStreamReader != NULL);

    FdoByte buff[4096];
    FdoInt64 cntTotal = 0;
    FdoInt32 cntRead = 0;
    do
    {
        cntRead = byteStreamReader->ReadNext (buff, 0 , 4096);
        cntTotal += cntRead;
    }
    while (cntRead);

    CPPUNIT_ASSERT (cntTotal > 0);
    CPPUNIT_ASSERT (!featReader->ReadNext ());

    connection->Close ();
}

void WcsTestSelect::testSelectSpatialExtents()
{
	try 
	{
        FdoPtr<FdoISelectAggregates> selAggr;
        FdoPtr<FdoIDataReader> rdr;
        FdoPtr<FdoIdentifierCollection> ids;
        FdoPtr<FdoExpression> expr;
        FdoPtr<FdoComputedIdentifier> cid;
        int count = 0;

		FdoPtr<FdoIConnection> conn = WcsTests::GetConnection();
		conn->SetConnectionString(L"FeatureServer=http://nsidc.org/cgi-bin/atlas_north");
		CPPUNIT_ASSERT(conn->Open() == FdoConnectionState_Open);

        FdoPtr<FdoFgfGeometryFactory> gf = FdoFgfGeometryFactory::GetInstance();
		
        FdoPtr<FdoISelectAggregates> advsel = (FdoISelectAggregates*)(conn->CreateCommand(FdoCommandType_SelectAggregates));
	    advsel->SetFeatureClassName(L"snow_water_equivalent_01");
	    ids = advsel->GetPropertyNames();
	    expr = FdoExpression::Parse(L"SpatialExtents(Raster)");
	    cid = FdoComputedIdentifier::Create(L"MBR", expr);
	    ids->Add(cid);
	    rdr = advsel->Execute();

	    count = 0;
	    FdoPtr<FdoIEnvelope> envelopeAllWithoutFilter;
	    while (rdr->ReadNext())
	    {
		    if ( rdr->IsNull(L"MBR") )
			    continue;

		    FdoPtr<FdoByteArray> geomBytes = rdr->GetGeometry(L"MBR");
		    FdoPtr<FdoIGeometry> geom = gf->CreateGeometryFromFgf(geomBytes);
		    envelopeAllWithoutFilter = geom->GetEnvelope();

		    if (envelopeAllWithoutFilter->GetIsEmpty())
			    CPPUNIT_FAIL("Expected non-empty envelope for SpatialExtents() result");

		    count++;
	    }
	    CPPUNIT_ASSERT_MESSAGE("Expected exactly one row of aggregate data", count==1);

	    rdr->Close();

	    CPPUNIT_ASSERT_MESSAGE("SpatialExtents results don't match (MinX)", fabs(envelopeAllWithoutFilter->GetMinX() - (-10700000.00)) < 0.0000001);
	    CPPUNIT_ASSERT_MESSAGE("SpatialExtents results don't match (MinY)", fabs(envelopeAllWithoutFilter->GetMinY() - (-10700000.00)) < 0.0000001);
	    CPPUNIT_ASSERT_MESSAGE("SpatialExtents results don't match (MaxX)", fabs(envelopeAllWithoutFilter->GetMaxX() - (14700000.00)) < 0.0000001);
	    CPPUNIT_ASSERT_MESSAGE("SpatialExtents results don't match (MaxY)", fabs(envelopeAllWithoutFilter->GetMaxY() - (14700000.00)) < 0.0000001); 

        /////////////////////////

	    advsel->SetFeatureClassName(L"sea_ice_concentration_07");
	    rdr = advsel->Execute();

	    count = 0;
	    while (rdr->ReadNext())
	    {
		    if ( rdr->IsNull(L"MBR") )
			    continue;

		    FdoPtr<FdoByteArray> geomBytes = rdr->GetGeometry(L"MBR");
		    FdoPtr<FdoIGeometry> geom = gf->CreateGeometryFromFgf(geomBytes);
		    envelopeAllWithoutFilter = geom->GetEnvelope();

		    if (envelopeAllWithoutFilter->GetIsEmpty())
			    CPPUNIT_FAIL("Expected non-empty envelope for SpatialExtents() result");

		    count++;
	    }
	    CPPUNIT_ASSERT_MESSAGE("Expected exactly one row of aggregate data", count==1);

	    rdr->Close();

	    CPPUNIT_ASSERT_MESSAGE("SpatialExtents results don't match (MinX)", fabs(envelopeAllWithoutFilter->GetMinX() - (-3961770.085 )) < 0.0000001);
	    CPPUNIT_ASSERT_MESSAGE("SpatialExtents results don't match (MinY)", fabs(envelopeAllWithoutFilter->GetMinY() - (-3961769.906)) < 0.0000001);
	    CPPUNIT_ASSERT_MESSAGE("SpatialExtents results don't match (MaxX)", fabs(envelopeAllWithoutFilter->GetMaxX() - (3961769.894 )) < 0.0000001);
	    CPPUNIT_ASSERT_MESSAGE("SpatialExtents results don't match (MaxY)", fabs(envelopeAllWithoutFilter->GetMaxY() - (4362961.971)) < 0.0000001);

        conn->Close();
    }
	catch( FdoException *ex )
    {
        fail(ex);
    }
}
//